home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 22
/
Cream of the Crop 22.iso
/
program
/
cgazv4n3.zip
/
FILES.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-02-06
|
7KB
|
294 lines
/****************************** FILES.C *******************************
* Author: John Rex
* Date: October, 1989
* Compilers: MSC 5.1
* Turbo C 2.0
* Operating Systems: DOS and OS/2
* Memory Models: any
* Purpose: file name manipulation routines:
* normal_name() - normalizes a partial file name to one with
* drive and correct path (all \.. stuff removed)
* add_ext() - add a file extension
* del_ext() - delete file extension
*
* Compile time switches: TEST brings in a test driver
* OS2 to get OS/2 compile (MSC only)
*
* Sample OS/2 compile lines:
* OS/2 only version: cl /G2 /DOS2 /Lp /DTEST files.c
* OS/2 or DOS (bound): cl /G2 /DOS2 /Lp /DTEST files.c /Fbbfiles.exe
*
* Source code may be freely used if authorship is acknowledged
* Object code may be freely used
**********************************************************************/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#if !defined (OS2) /* DOS only stuff */
#include <dos.h>
/* define our own versions to avoid bugs with MSC's versions */
#define FP_GETOFF(p) ((unsigned) (p))
#define FP_GETSEG(p) ((unsigned) ((unsigned long)(p) >> 16) )
union REGS dataregs;
struct SREGS segregs;
#define _rax dataregs.x.ax
#define _rdx dataregs.x.dx
#define _rsi dataregs.x.si
#define _rds segregs.ds
#define _carryf dataregs.x.cflag
#define _doint(x) int86x(x,&dataregs,&dataregs,&segregs)
#define DOS_CALL 0x21
#define GET_DEF_DRIVE 0x1900
#define GET_DIR 0x4700
#else /* OS/2 */
#define INCL_DOS
#define INCL_NOPM /* save time - no PM stuff */
#include <os2.h>
#endif
int def_drive(void), get_directory(int, char *);
/* the character we use to delimit subdirs in final product */
#define delim '/'
char *normal_name(char *file, char *buffer)
/* given a filename of the form
[d:][path or partial path]filename
normal_name() will return a pointer to a string containing the fully
expanded path to the file. The partial path may use / or \ and it
may use the .. operator for backup in a directory tree. NULL is
returned if the path parse fails. The var buffer is used as the work
area - the returned pointer will be to buffer (if it's not a NULL).
*/
{
char path[100];
char *p, *s, save;
int drive;
/* first convert all \ & / to one style */
for (p = file; *p != '\0'; p++)
if (*p == '/')
*p = '\\';
/* are we given a drive? */
if ((p = strchr(file, ':')) != NULL) {
if (p - file != 1)
return(NULL); /* error */
drive = tolower(file[0]) - 'a';
file += 2;
}
else
drive = def_drive();
if (get_directory(drive, path + 1) == 0)
return(NULL);
path[0] = '\\'; /* DOS doesn't supply the leading \ */
/* now, march thru given file name and append to path */
/* if filename starts with '\', then must go back to root */
if (*file == '\\') {
path[1] = '\0'; /* set path to just a root */
file++;
}
/* path should always end in \ */
if (path[strlen(path) - 1] != '\\')
strcat(path, "\\");
/* now, look at each subdir in filename */
while((p = strchr(file, '\\')) != NULL) {
save = *++p;
*p = '\0';
if (file[0] == '.') { /* look at dot operator */
if (strcmp(file ,"..\\") == 0) { /* back up one subdir */
s = strrchr(path, '\\'); /* find start of previous subdir */
if (s == path)
s++;
else {
*s = '\0'; /* remove trailing \ */
s = strrchr(path, '\\') + 1; /* find preceeding \ */
}
*s = '\0';
}
else
; /* ignore other . commands */
}
else /* a subdir name */
strcat(path, file);
*p = save;
file = p;
}
/* and append the file name */
strcat(path, file);
/* return the fruit of our labors */
p = buffer;
p[0] = (char) ('a' + drive);
p[1] = '\0';
strcat(p, ":");
strcat(p, path);
for (s = p; *s != '\0'; s++) /* convert delimiters to final form */
if (*s == '\\')
*s = delim;
else
*s = (char) tolower(*s);
return(p);
}
static struct d_list { /* a place to keep a list of things we've looked up */
int drive;
char *dir;
struct d_list *next;
} *d_head = NULL;
int def_drive() /* return current default drive. 0 = A, 1 = B, etc. */
{
#if !defined (OS2)
_rax = GET_DEF_DRIVE;
_doint(DOS_CALL);
return(_rax & 0xFF);
#else
USHORT usDriveNumber;
ULONG ulLogicalDrives;
DosQCurDisk(&usDriveNumber, &ulLogicalDrives);
return(usDriveNumber - 1);
#endif
}
int get_directory(drive, buffer) /* get current directory for drive */
int drive; /* 0 = A, 1 = B, etc. */
char *buffer; /* put result here */
{
struct d_list *d_ptr;
#if defined(OS2)
USHORT cbPath;
#endif
/* do we already know this one? */
for (d_ptr = d_head; d_ptr != NULL; d_ptr = d_ptr -> next)
if (d_ptr -> drive == drive) { /* found it */
strcpy(buffer, d_ptr -> dir);
return(1);
}
/* haven't looked this one up - find out about it */
#if !defined(OS2)
buffer[0] = '\0'; /* terminate the buffer */
_rax = GET_DIR;
_rdx = (unsigned) (drive + 1);
_rds = FP_GETSEG((void far *) buffer);
_rsi = FP_GETOFF((void far *) buffer);
_doint(DOS_CALL);
if (_carryf)
return(0); /* something went wrong */
#else /* OS/2 */
if (DosQCurDir(drive+1, buffer, &cbPath))
return (0); /* something went wrong */
#endif
else { /* success */
/* store a copy of what we found */
d_ptr = (struct d_list *) malloc(sizeof(struct d_list));
d_ptr -> next = d_head;
d_head = d_ptr;
d_ptr -> drive = drive;
d_ptr -> dir = malloc((unsigned) (strlen(buffer) + 1));
strcpy(d_ptr -> dir, buffer);
/* and return */
return(1);
}
}
/* routines to add or remove file extensions */
char *last_dot(char *file) /* find the dot of the file.ext portion of a filename */
{
char *s;
if ((s = strrchr(file, '/' )) != NULL) ;
else if ((s = strrchr(file, '\\')) != NULL) ;
else s = file;
return(strrchr(s, '.'));
}
void delext(file) /* remove the extension from a file name */
char *file;
{
char *s;
s = last_dot(file);
if (s != NULL)
*s = '\0';
}
void addext(file, ext) /* add an extension unless one is already present */
char *file;
char *ext;
{
char *s;
s = last_dot(file);
if (s == NULL) {
strcat(file, ".");
strcat(file, ext);
}
}
#ifdef TEST /* If defined, run the test driver */
int cdecl main(argc, argv)
int argc;
char **argv;
{
char *s, buf[100], work[100];
if (argc < 2)
puts("Syntax is: files file_1 file_2 ...\n");
else {
argc--;
argv++;
while(argc--) {
strcpy(buf, *argv++);
puts(buf);
puts(" is altered to ");
delext(buf);
addext(buf, "zzz");
puts(buf);
puts("\n");
s = normal_name(buf, work);
puts(buf);
puts(" becomes ");
if (s != NULL)
puts(s);
else
puts("path parse failed");
puts("\n");
puts("\n");
}
}
}
#endif